home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
scheme
/
boxer
/
boxer.lha
/
grfdfs.lisp
< prev
next >
Wrap
Text File
|
1993-07-17
|
21KB
|
520 lines
;; -*- Mode:LISP; Package:BOXER; Base:10.;fonts:cptfont,cptfontb; -*-
#|
Copyright 1984 Massachusetts Institute of Technology
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of M.I.T. not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission. M.I.T. makes no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied warranty.
+-Data--+
This file is part of the | BOXER | system
+-------+
This contains all of the Interface between Graphics sheets
and the rest of the BOXER Editor. The functions and methods
which manipulate pixels (as opposed to graphics objects) can
also be found here In particular, the functions which are
used to draw lines, regions, etc are here.
|#
;;; get the offsets right
(DEFMACRO WITH-TURTLE-SLATE-ORIGINS (SCREEN-BOX &BODY BODY)
;; this macro sets x and y coordinates of top left of turtle array
;; not that the a SCREEN-SHEET may NOT have been allocated if this has been called BEFORE
;; Redisplay has had a chnace to run
`(LET ((SCREEN-SHEET (TELL-CHECK-NIL ,SCREEN-BOX :SCREEN-SHEET)))
(UNLESS (NULL SCREEN-SHEET)
(MULTIPLE-VALUE-BIND (BOX-X-OFFSET BOX-Y-OFFSET)
(TELL ,SCREEN-BOX :POSITION)
(MULTIPLE-VALUE-BIND (SHEET-X SHEET-Y)
(GRAPHICS-SCREEN-SHEET-OFFSETS SCREEN-SHEET)
(LET ((%ORIGIN-X-OFFSET (+ (TV:SHEET-INSIDE-LEFT *BOXER-PANE*)
BOX-X-OFFSET
SHEET-X))
(%ORIGIN-Y-OFFSET (+ (TV:SHEET-INSIDE-TOP *BOXER-PANE*)
BOX-Y-OFFSET
SHEET-Y)))
(PROGN . ,BODY)))))))
(DEFVAR *SCRUNCH-FACTOR* 1
"the factor used to normalize the Y-coordinates so that squares really are")
(DEFUN MAKE-GRAPHICS-SHEET (WID HEI &OPTIONAL BOX)
(%MAKE-GRAPHICS-SHEET WID HEI (TV:MAKE-SHEET-BIT-ARRAY *BOXER-PANE* WID HEI) BOX))
(DEFUN MAKE-GRAPHICS-SCREEN-SHEET (ACTUAL-OBJ &OPTIONAL (X-OFFSET 0.) (Y-OFFSET 0.))
(%MAKE-G-SCREEN-SHEET ACTUAL-OBJ X-OFFSET Y-OFFSET))
(DEFUN GRAPHICS-SCREEN-SHEET-OFFSETS (GRAPHICS-SCREEN-SHEET)
(VALUES (GRAPHICS-SCREEN-SHEET-X-OFFSET GRAPHICS-SCREEN-SHEET)
(GRAPHICS-SCREEN-SHEET-Y-OFFSET GRAPHICS-SCREEN-SHEET)))
(DEFUN SET-GRAPHICS-SCREEN-SHEET-X-OFFSET (GRAPHICS-SCREEN-SHEET NEW-X-OFFSET)
(SETF (GRAPHICS-SCREEN-SHEET-X-OFFSET GRAPHICS-SCREEN-SHEET) NEW-X-OFFSET))
(DEFUN SET-GRAPHICS-SCREEN-SHEET-Y-OFFSET (GRAPHICS-SCREEN-SHEET NEW-Y-OFFSET)
(SETF (GRAPHICS-SCREEN-SHEET-Y-OFFSET GRAPHICS-SCREEN-SHEET) NEW-Y-OFFSET))
;;accessors for graphics boxes
(DEFMETHOD (GRAPHICS-BOX :BIT-ARRAY) ()
(GRAPHICS-SHEET-BIT-ARRAY GRAPHICS-SHEET))
(DEFMETHOD (GRAPHICS-BOX :GRAPHICS-SHEET) ()
GRAPHICS-SHEET)
(DEFUN DRAWING-WIDTH (GRAPHICS-SHEET)
;; Returns the width of the area of a bit-array for a graphics
;; box. Note that this doesn't have to be = to
;; ARRAY-DIMENSION-N because of BITBLT's multiple of 32.
;; requirement
(GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET))
(DEFUN DRAWING-HEIGHT (GRAPHICS-SHEET)
(GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET))
(DEFMETHOD (GRAPHICS-BOX :BIT-ARRAY-WID) ()
(GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET))
(DEFMETHOD (GRAPHICS-BOX :BIT-ARRAY-HEI) ()
(GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET))
(DEFMETHOD (GRAPHICS-BOX :GRAPHICS-SHEET-SIZE) ()
(VALUES (GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET)
(GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET)))
(DEFMETHOD (GRAPHICS-BOX :DRAW-MODE) ()
(GRAPHICS-SHEET-DRAW-MODE GRAPHICS-SHEET))
(DEFMETHOD (GRAPHICS-BOX :SET-DRAW-MODE) (NEW-MODE)
(SETF (GRAPHICS-SHEET-DRAW-MODE GRAPHICS-SHEET) NEW-MODE))
(DEFMETHOD (GRAPHICS-BOX :CLEAR-BOX) ()
(DOLIST (SCREEN-BOX (GET-VISIBLE-SCREEN-OBJS SELF))
(UNLESS (EQ ':SHRUNK (TELL SCREEN-BOX :DISPLAY-STYLE))
(DRAWING-ON-TURTLE-SLATE SCREEN-BOX
(TV:%DRAW-RECTANGLE (GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET)
(GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET)
(SCALE-X 0)
(SCALE-Y 0)
TV:ALU-ANDCA
%DRAWING-ARRAY))))
(TV:%DRAW-RECTANGLE (GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET)
(GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET)
0
0
TV:ALU-ANDCA
(GRAPHICS-SHEET-BIT-ARRAY GRAPHICS-SHEET)))
(DEFMETHOD (GRAPHICS-BOX :ERASE-FROM-SCREEN) ()
(DRAWING-ON-WINDOW (*BOXER-PANE*)
(DOLIST (SCREEN-BOX (GET-VISIBLE-SCREEN-OBJS SELF))
(UNLESS (EQ ':SHRUNK (TELL SCREEN-BOX :DISPLAY-STYLE))
(WITH-TURTLE-SLATE-ORIGINS SCREEN-BOX
(TV:%DRAW-RECTANGLE
(GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET)
(GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET)
%ORIGIN-X-OFFSET
%ORIGIN-Y-OFFSET
TV:ALU-ANDCA
%DRAWING-WINDOW))))))
(DEFMETHOD (GRAPHICS-BOX :CLEARSCREEN) ()
(TELL SELF :CLEAR-BOX)
(DOLIST (TURTLE (GRAPHICS-SHEET-OBJECT-LIST GRAPHICS-SHEET))
(IF (TELL TURTLE :SHOWN-P)
(TELL TURTLE :DRAW))))
(DEFMETHOD (GRAPHICS-BOX :COPY) ()
(LET ((NEW-BOX (MAKE-INITIALIZED-GRAPHICS-BOX ':FIXED-WID (DRAWING-WIDTH GRAPHICS-SHEET)
':FIXED-HEI (DRAWING-HEIGHT GRAPHICS-SHEET)))
(BOX-STREAM (MAKE-BOX-STREAM SELF)))
(TELL NEW-BOX :SET-CONTENTS-FROM-STREAM BOX-STREAM T)
(WHEN (NOT-NULL PORTS)
(PUSH (CONS SELF NEW-BOX) .LINK-TARGET-ALIST.))
(BITBLT TV:ALU-SETA (DRAWING-WIDTH GRAPHICS-SHEET) (DRAWING-HEIGHT GRAPHICS-SHEET)
(GRAPHICS-SHEET-BIT-ARRAY GRAPHICS-SHEET) 0 0
(TELL NEW-BOX :BIT-ARRAY) 0 0)
(tell new-box :export-all-variables)
NEW-BOX))
(DEFMETHOD (GRAPHICS-BOX :COMPLEMENT) ()
(TV:%DRAW-RECTANGLE (GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET)
(GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET)
0
0
TV:ALU-XOR
(GRAPHICS-SHEET-BIT-ARRAY GRAPHICS-SHEET))
(TELL SELF :MODIFIED))
;;;ED -- I've never used these and don't know if they work
(DEFMETHOD (GRAPHICS-BOX :FILL-FROM-GRAPHICS-BOX) (FROM-BOX)
(LET* ((FROM-SHEET (TELL FROM-BOX :GRAPHICS-SHEET))
(FROM-WID (GRAPHICS-SHEET-DRAW-WID FROM-SHEET));need these values if we want to erase
(FROM-HEI (GRAPHICS-SHEET-DRAW-HEI FROM-SHEET));unused space in the destination
(TO-WID (GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET))
(TO-HEI (GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET)))
FROM-WID FROM-HEI ;bound but never used
(BITBLT TV:ALU-SETA (MIN FROM-WID TO-WID) (MIN TO-HEI FROM-HEI)
(GRAPHICS-SHEET-BIT-ARRAY FROM-SHEET)
0 0 (GRAPHICS-SHEET-BIT-ARRAY GRAPHICS-SHEET) 0 0))
(TELL SELF :MODIFIED))
(DEFMETHOD (GRAPHICS-BOX :PLACE-STAMP-WITH-CLIPPING) (FROM-BOX X Y &OPTIONAL(ALU TV:ALU-SETA))
(LET* ((FROM-SHEET (TELL FROM-BOX :GRAPHICS-SHEET))
(FROM-WID (GRAPHICS-SHEET-DRAW-WID FROM-SHEET));need these values if we want to erase
(FROM-HEI (GRAPHICS-SHEET-DRAW-HEI FROM-SHEET));unused space in the destination
(TO-WID (GRAPHICS-SHEET-DRAW-WID GRAPHICS-SHEET))
(TO-HEI (GRAPHICS-SHEET-DRAW-HEI GRAPHICS-SHEET)))
(BITBLT ALU (MIN FROM-WID (- TO-WID X)) (MIN FROM-HEI (- TO-HEI Y))
(GRAPHICS-SHEET-BIT-ARRAY FROM-SHEET)
0 0 (GRAPHICS-SHEET-BIT-ARRAY GRAPHICS-SHEET) X Y))
(TELL SELF :MODIFIED))
(DEFUN MAKE-GRAPHICS-BOX (&OPTIONAL (WID *DEFAULT-GRAPHICS-BOX-WID*)
(HEI *DEFAULT-GRAPHICS-BOX-HEI*))
(LET ((GB (MAKE-INITIALIZED-GRAPHICS-BOX ':FIXED-WID WID ':FIXED-HEI HEI)))
GB))
;;; low level drawing utilities
;;Following functions divide a floating point coordinate
;;position into a "screen" [integer multiple of screen size] and
;;fraction of screen from the left or bottom edge. NOTE that
;;ALL these functions are meant to operate on ARRAY coords
;;; drawing defs
(DEFVAR %BIT-ARRAY NIL
"The bit-array of the graphics-box being operated on")
(DEFVAR %DRAWING-WIDTH NIL
"The width of the bit-array of the graphics box in which we are allowed to draw")
(DEFVAR %DRAWING-HEIGHT NIL
"The height of the bit-array of the graphics box in which we are allowed to draw")
(DEFVAR %GRAPHICS-BOX NIL
"The graphics box which is being operated on.")
(DEFVAR %DRAW-MODE NIL
"Draw-mode of the graphics box in which we are allowed to draw")
(DEFMACRO WITH-GRAPHICS-VARS-BOUND (TO-BOX &BODY BODY)
"This macro sets up an environment where commonly used parameters of the graphics box are bound. "
`(LET* ((GR-SHEET (TELL ,TO-BOX :GRAPHICS-SHEET))
(%BIT-ARRAY (GRAPHICS-SHEET-BIT-ARRAY GR-SHEET))
(%DRAWING-WIDTH (1- (GRAPHICS-SHEET-DRAW-WID GR-SHEET)))
(%DRAWING-HEIGHT (1- (GRAPHICS-SHEET-DRAW-HEI GR-SHEET)))
(%GRAPHICS-BOX ,TO-BOX)
(%DRAW-MODE (GRAPHICS-SHEET-DRAW-MODE GR-SHEET)))
(PROGN . ,BODY)))
;; Here is the line drawing stuff
;;; This is the highest level drawing command.
(DEFUN CK-MODE-DRAW-LINE (FROM-X FROM-Y TO-X TO-Y &OPTIONAL (ALU TV:ALU-XOR))
(IF (EQ %DRAW-MODE ':WRAP)
(DRAW-WRAP-LINE FROM-X FROM-Y TO-X TO-Y ALU)
(DRAW-WINDOW-LINE FROM-X FROM-Y TO-X TO-Y ALU)))
(DEFSUBST OUT-OF-RANGE? (X0 Y0 X1 Y1)
(OR (AND (< X0 0) (< X1 0))
(AND (> X0 %DRAWING-WIDTH) (> X1 %DRAWING-WIDTH))
(AND (< Y1 0) (< Y0 0))
(AND (> Y0 %DRAWING-HEIGHT) (> Y1 %DRAWING-HEIGHT))))
(DEFUN DRAW-WINDOW-LINE (X0 Y0 X1 Y1 ALU)
(UNLESS (OUT-OF-RANGE? X0 Y0 X1 Y1)
(DRAW-VECTOR-WITH-CLIPPING X0 Y0 X1 Y1 ALU)))
(DEFSUBST WINDOW-CLIP-X (X-POS)
(MIN (1- %DRAWING-WIDTH) (MAX X-POS 0)))
(DEFSUBST WINDOW-CLIP-Y (Y-POS)
(MIN (1- %DRAWING-HEIGHT) (MAX Y-POS 0)))
;;; This works in some tricky places where gregor's routine doesn't
(DEFUN CALC-CLIPPED-VECTOR (X0 Y0 X1 Y1)
(COND ((AND (POINT-IN-ARRAY? X0 Y0) (POINT-IN-ARRAY? X1 Y1))
(VALUES X0 Y0 X1 Y1))
((= X0 X1)
(VALUES X0 (WINDOW-CLIP-Y Y0) X1 (WINDOW-CLIP-Y Y1)))
((= Y0 Y1)
(VALUES (WINDOW-CLIP-X X0) Y0 (WINDOW-CLIP-X X1) Y0))
(T
(LET ((X-LENGTH (FLOAT (- X1 X0))) (Y-LENGTH (FLOAT (- Y1 Y0)))
(CLIPPED-X0 (WINDOW-CLIP-X X0))
(CLIPPED-Y0 (WINDOW-CLIP-Y Y0))
(CLIPPED-X1 (WINDOW-CLIP-X X1))
(CLIPPED-Y1 (WINDOW-CLIP-Y Y1)))
(IF (< (// (FLOAT (- CLIPPED-X1 X0))
X-LENGTH)
(// (FLOAT (- CLIPPED-Y1 Y0))
Y-LENGTH))
(SETQ CLIPPED-Y1 (+ Y0 (* (- CLIPPED-X1 X0)
(// Y-LENGTH X-LENGTH))))
(SETQ CLIPPED-X1 (+ X0 (* (- CLIPPED-Y1 Y0)
(// X-LENGTH Y-LENGTH)))))
(IF (< (// (FLOAT (- X1 CLIPPED-X0))
X-LENGTH)
(// (FLOAT (- Y1 CLIPPED-Y0))
Y-LENGTH))
(SETQ CLIPPED-Y0 (- Y1 (* (- X1 CLIPPED-X0)
(// Y-LENGTH X-LENGTH))))
(SETQ CLIPPED-X0 (- X1 (* (- Y1 CLIPPED-Y0)
(// X-LENGTH Y-LENGTH)))))
(WHEN (POINT-IN-ARRAY? (FIXR CLIPPED-X0) (FIXR CLIPPED-Y0))
(VALUES (FIXR CLIPPED-X0) (FIXR CLIPPED-Y0)
(FIXR CLIPPED-X1) (FIXR CLIPPED-Y1)))))))
;;; This function clips a vector and draws it both to the
;;; graphics-box bit array and to each visible screen object.
(DEFUN DRAW-VECTOR-WITH-CLIPPING (X0 Y0 X1 Y1 ALU)
(MULTIPLE-VALUE-BIND (CLIPPED-X0 CLIPPED-Y0 CLIPPED-X1 CLIPPED-Y1)
(CALC-CLIPPED-VECTOR X0 Y0 X1 Y1)
(WHEN CLIPPED-X0
(DRAW-VECTOR CLIPPED-X0 CLIPPED-Y0 CLIPPED-X1 CLIPPED-Y1 ALU))))
;;; The following does not check clipping --- use with care !!!
(DEFUN DRAW-VECTOR (CLIPPED-X0 CLIPPED-Y0 CLIPPED-X1 CLIPPED-Y1 ALU)
(LET ((END-POINT? (NOT (= ALU TV:ALU-XOR))))
(WITHOUT-INTERRUPTS
(WHEN (GRAPHICS-BOX? %GRAPHICS-BOX)
(DOLIST (SCREEN-BOX (GET-VISIBLE-SCREEN-OBJS %GRAPHICS-BOX))
(UNLESS (EQ ':SHRUNK (TELL SCREEN-BOX :DISPLAY-STYLE))
(DRAWING-ON-TURTLE-SLATE SCREEN-BOX
(SYS:%DRAW-LINE (SCALE-X CLIPPED-X0) (SCALE-Y CLIPPED-Y0)
(SCALE-X CLIPPED-X1) (SCALE-Y CLIPPED-Y1)
ALU END-POINT? %DRAWING-ARRAY)))))
(SYS:%DRAW-LINE CLIPPED-X0 CLIPPED-Y0 CLIPPED-X1 CLIPPED-Y1
ALU END-POINT? %BIT-ARRAY))))
(DEFUN DRAW-WRAP-LINE (FROM-X FROM-Y TO-X TO-Y &OPTIONAL (ALU TV:ALU-XOR))
"Draws vector allowing wraparound. Arguments in ARRAY coordinates."
(LET ((FROM-SCREEN-X (SCREEN-X FROM-X))
(FROM-SCREEN-Y (SCREEN-Y FROM-Y))
(TO-SCREEN-X (SCREEN-X TO-X))
(TO-SCREEN-Y (SCREEN-Y TO-Y)))
(LET ((FROM-FRACTION-X (SCREEN-FRACTION-X FROM-SCREEN-X FROM-X))
(FROM-FRACTION-Y (SCREEN-FRACTION-Y FROM-SCREEN-Y FROM-Y))
(TO-FRACTION-X (SCREEN-FRACTION-X TO-SCREEN-X TO-X))
(TO-FRACTION-Y (SCREEN-FRACTION-Y TO-SCREEN-Y TO-Y)))
;;Split up into screens and fractions of screens, then hand off
;;to WRAP-SCREEN-VECTOR.
(WRAP-SCREEN-VECTOR FROM-SCREEN-X FROM-FRACTION-X
FROM-SCREEN-Y FROM-FRACTION-Y
TO-SCREEN-X TO-FRACTION-X
TO-SCREEN-Y TO-FRACTION-Y
ALU))))
(DEFUN SCREEN-X (WRAP-X)
(IF (MINUSP WRAP-X)
(1- (FIX (// WRAP-X %DRAWING-WIDTH))) ;PERHAPS 1+
(FIX (// WRAP-X %DRAWING-WIDTH))))
(DEFUN SCREEN-Y (WRAP-Y)
(IF (MINUSP WRAP-Y)
(1- (FIX (// WRAP-Y %DRAWING-HEIGHT)))
(FIX (// WRAP-Y %DRAWING-HEIGHT))))
(DEFUN SCREEN-FRACTION-X (SCREEN-WIDS WRAP-X)
(// (FLOAT (- WRAP-X (* SCREEN-WIDS %DRAWING-WIDTH)))
%DRAWING-WIDTH))
(DEFUN SCREEN-FRACTION-Y (SCREEN-HEIS WRAP-Y)
(// (FLOAT (- WRAP-Y (* SCREEN-HEIS %DRAWING-HEIGHT)))
%DRAWING-HEIGHT))
(DEFUN WRAP-SCREEN-VECTOR (FROM-SCREEN-X FROM-FRACTION-X FROM-SCREEN-Y FROM-FRACTION-Y
TO-SCREEN-X TO-FRACTION-X TO-SCREEN-Y TO-FRACTION-Y
ALU
&AUX TO-EDGE-X SIGN-X TO-EDGE-Y SIGN-Y
FROM-EDGE-FRACTION TO-EDGE-FRACTION)
(WITHOUT-INTERRUPTS
(COND ((NOT (= FROM-SCREEN-X TO-SCREEN-X))
;; Vector crosses a X screen edge.
(LET ((CHANGE-X (+ (- TO-SCREEN-X FROM-SCREEN-X)
(- TO-FRACTION-X FROM-FRACTION-X)))
(CHANGE-Y (+ (- TO-SCREEN-Y FROM-SCREEN-Y)
(- TO-FRACTION-Y FROM-FRACTION-Y))))
(IF (PLUSP CHANGE-X)
(SETQ SIGN-X 1.
TO-EDGE-X (- 1.0 FROM-FRACTION-X)
FROM-EDGE-FRACTION 1.0
TO-EDGE-FRACTION 0.0)
(SETQ SIGN-X -1.
TO-EDGE-X (- FROM-FRACTION-X)
FROM-EDGE-FRACTION 0.0
TO-EDGE-FRACTION 1.0))
;; compute the X and Y coordinates to split the vector at the X edge
(LET* ((EDGE-FRACTION-Y (+ FROM-FRACTION-Y
(* TO-EDGE-X (// CHANGE-Y CHANGE-X))))
(EDGE-SCREEN-Y FROM-SCREEN-Y)
(FIX-EDGE-FRACTION (FIX EDGE-FRACTION-Y)))
(INCF EDGE-SCREEN-Y FIX-EDGE-FRACTION)
(SETQ EDGE-FRACTION-Y (- EDGE-FRACTION-Y (FLOAT FIX-EDGE-FRACTION)))
;; draw a vector from the FROM point to the edge...
(WRAP-SCREEN-VECTOR FROM-SCREEN-X FROM-FRACTION-X
FROM-SCREEN-Y FROM-FRACTION-Y
FROM-SCREEN-X FROM-EDGE-FRACTION
EDGE-SCREEN-Y EDGE-FRACTION-Y
ALU)
;; ...and then continue on to the TO point
(WRAP-SCREEN-VECTOR (+ FROM-SCREEN-X SIGN-X)
TO-EDGE-FRACTION
EDGE-SCREEN-Y EDGE-FRACTION-Y
TO-SCREEN-X TO-FRACTION-X
TO-SCREEN-Y TO-FRACTION-Y
ALU))))
((NOT (= FROM-SCREEN-Y TO-SCREEN-Y))
;; Vector crosses a Y screen edge
(LET ((CHANGE-X (+ (- TO-SCREEN-X FROM-SCREEN-X)
(- TO-FRACTION-X FROM-FRACTION-X)))
(CHANGE-Y (+ (- TO-SCREEN-Y FROM-SCREEN-Y)
(- TO-FRACTION-Y FROM-FRACTION-Y))))
(IF (PLUSP CHANGE-Y)
(SETQ SIGN-Y 1.
TO-EDGE-Y (- 1.0 FROM-FRACTION-Y)
FROM-EDGE-FRACTION 1.0
TO-EDGE-FRACTION 0.0)
(SETQ SIGN-Y -1.
TO-EDGE-Y (- FROM-FRACTION-Y)
FROM-EDGE-FRACTION 0.0
TO-EDGE-FRACTION 1.0))
;; compute the X and Y coordinates to split the vector at the Y edge
(LET* ((EDGE-FRACTION-X (+ FROM-FRACTION-X
(* TO-EDGE-Y (// CHANGE-X CHANGE-Y))))
(EDGE-SCREEN-X FROM-SCREEN-X)
(FIX-EDGE-FRACTION (FIX EDGE-FRACTION-X)))
(INCF EDGE-SCREEN-X FIX-EDGE-FRACTION)
(SETQ EDGE-FRACTION-X (- EDGE-FRACTION-X (FLOAT FIX-EDGE-FRACTION)))
;; draw a vector from the FROM point to the edge...
(WRAP-SCREEN-VECTOR FROM-SCREEN-X FROM-FRACTION-X
FROM-SCREEN-Y FROM-FRACTION-Y
EDGE-SCREEN-X EDGE-FRACTION-X
FROM-SCREEN-Y FROM-EDGE-FRACTION
ALU)
;; ...and then continue on to the TO point
(WRAP-SCREEN-VECTOR EDGE-SCREEN-X EDGE-FRACTION-X
(+ FROM-SCREEN-Y SIGN-Y) TO-EDGE-FRACTION
TO-SCREEN-X TO-FRACTION-X
TO-SCREEN-Y TO-FRACTION-Y
ALU))))
(T ;looks like its cool to draw the line as is
(LET ((X0 (FIXR (* %DRAWING-WIDTH FROM-FRACTION-X)))
(Y0 (FIXR (* %DRAWING-HEIGHT FROM-FRACTION-Y)))
(X1 (FIXR (* %DRAWING-WIDTH TO-FRACTION-X)))
(Y1 (FIXR (* %DRAWING-HEIGHT TO-FRACTION-Y))))
(DRAW-VECTOR X0 Y0 X1 Y1 ALU))))))
;;; This function draw a list of vectors and strings. The below
;;; is what draws a turtle's shape given its vector list
;;; repesentation. I think the iteration construct could be
;;; written more cleanly.
(DEFCONST *DEFAULT-GRAPHICS-FONT* FONTS:TVFONT
"The font used for drawing in graphics boxes")
(DEFCONST *FONT-WIDTH* (FONT-CHAR-WIDTH *DEFAULT-GRAPHICS-FONT*))
(DEFCONST *FONT-HEIGHT* (FONT-CHAR-HEIGHT *DEFAULT-GRAPHICS-FONT*))
(DEFUN DRAW-VECTOR-LIST (V-LIST SIZE START-X START-Y HEADING &OPTIONAL (ALU TV:ALU-XOR))
(D-V-L-ITER V-LIST START-X START-Y (* SIZE (COSD HEADING)) (* SIZE (SIND HEADING)) 'D ALU))
(DEFUN D-V-L-ITER (V-LIST START-X START-Y COS-HEAD SIN-HEAD PEN ALU)
(DO ()
((NULL V-LIST))
(COND
((MEMQ (FIRST V-LIST) '(UP :UP :ERASE ERASE))
(SETQ PEN 'U V-LIST (CDR V-LIST)))
((MEMQ (FIRST V-LIST) '(DOWN XOR :DOWN :XOR))
(SETQ PEN 'D V-LIST (CDR V-LIST)))
((STRINGP (FIRST V-LIST))
(WHEN (EQ PEN 'D)
(LET ((XPOS (FIXR (+ 3. START-X))) (YPOS (FIXR (1+ START-Y))))
(DRAW-STRING-TO-GBOX (FIRST V-LIST) XPOS YPOS)))
(SETQ V-LIST (CDR V-LIST)))
;; compatibility with an old format. remove this soon 6/30/85
((LISTP (FIRST V-LIST))
(WHEN (EQ PEN 'D)
(LET ((XPOS (FIXR (+ 3. START-X))) (YPOS (FIXR (1+ START-Y))))
(DRAW-STRING-TO-GBOX (CAR (FIRST V-LIST)) XPOS YPOS)))
(SETQ V-LIST (CDR V-LIST)))
(T
(LET ((END-X (+ START-X
(* (FIRST V-LIST) COS-HEAD)
(* (SECOND V-LIST) (- SIN-HEAD))))
(END-Y (+ START-Y
(* (+ (* (FIRST V-LIST) SIN-HEAD)
(* (SECOND V-LIST) COS-HEAD))
*SCRUNCH-FACTOR*))))
(WHEN (EQ PEN 'D)
(DRAW-WINDOW-LINE (FIXR START-X) (FIXR START-Y)
(FIXR END-X) (FIXR END-Y) ALU))
(SETQ START-X END-X START-Y END-Y V-LIST (CDDR V-LIST)))))))
;;; drawing chars on graphics windows
(DEFSUBST CLIP-STRING (STRING X-POS)
(LET ((NEW-LENGTH (MIN (STRING-LENGTH STRING)
(FIXR (// (- %DRAWING-WIDTH X-POS) *FONT-WIDTH*)))))
(SUBSTRING STRING 0 NEW-LENGTH)))
;;; no CR's
(DEFUN DRAW-SIMPLE-STRING-TO-GBOX (STRING X-POS Y-POS ALU)
(IF (NOT (AND (POINT-IN-ARRAY? X-POS Y-POS)
(POINT-IN-ARRAY? X-POS (+ Y-POS *FONT-HEIGHT*))))
NIL ;;; can not print string at all
(LET* ((CLIPPED-STRING (CLIP-STRING STRING X-POS))
(CHAR-LIST (MAPCAR (FUNCTION CHARACTER)
(LISTARRAY CLIPPED-STRING))))
(WITHOUT-INTERRUPTS
;;; draw to the bit array
(LET ((CURSOR X-POS))
(DOLIST (CHAR CHAR-LIST)
(SYS:%DRAW-CHAR *DEFAULT-GRAPHICS-FONT*
CHAR CURSOR Y-POS ALU %BIT-ARRAY)
(SETQ CURSOR (+ CURSOR *FONT-WIDTH*))))
;;; draw to each visible screen object
(WHEN (GRAPHICS-BOX? %GRAPHICS-BOX)
(DRAWING-ON-WINDOW (*BOXER-PANE*)
(DOLIST (SCREEN-BOX (GET-VISIBLE-SCREEN-OBJS %GRAPHICS-BOX))
(UNLESS (EQ ':SHRUNK (TELL SCREEN-BOX :DISPLAY-STYLE))
(WITH-TURTLE-SLATE-ORIGINS SCREEN-BOX ;
(LET ((CURSOR-X (+ X-POS %ORIGIN-X-OFFSET))
(CURSOR-Y (+ Y-POS %ORIGIN-Y-OFFSET)))
(DOLIST (CHAR CHAR-LIST)
(SYS:%DRAW-CHAR *DEFAULT-GRAPHICS-FONT*
CHAR CURSOR-X CURSOR-Y ALU %DRAWING-ARRAY)
(SETQ CURSOR-X (+ CURSOR-X *FONT-WIDTH*)))
)))))))
CLIPPED-STRING)))
;;; CR's are allowed
(DEFUN DRAW-STRING-TO-GBOX (STRING X-POS START-Y-POS &OPTIONAL (ALU TV:ALU-XOR))
(LOOP WITH START = 0
WITH Y-POS = START-Y-POS
FOR INDEX FROM 0 TO (1- (STRING-LENGTH STRING))
FOR CHA = (AREF STRING INDEX)
WHEN (OR (CHAR= CHA #\CR) (CHAR= CHA #\LINE))
DO (DRAW-SIMPLE-STRING-TO-GBOX (NSUBSTRING STRING START INDEX) X-POS Y-POS ALU)
(SETQ START (1+ INDEX)
Y-POS (+ Y-POS *FONT-HEIGHT*))
FINALLY
(DRAW-SIMPLE-STRING-TO-GBOX (NSUBSTRING STRING START INDEX) X-POS Y-POS ALU)))